﻿using DimensionsHelper.LanguageService.Symbols;
using DimensionsHelper.LanguageService.Syntax;

namespace DimensionsHelper.LanguageService;

/// <summary>
///     语法分析树中带有定义域的语句符号。
///     可能是<see cref="FunctionDeclaration" />、<see cref="ClassSignature" />、
///     <see cref="InterfaceSignature" />、<see cref="ModuleSignature" />、<see cref="EventSection" />
/// </summary>
public abstract class AnalysisStatementWithDomain : AnalysisDeclaration
{
    private readonly DomainSymbolTable _domainSymbolTable;
    protected readonly List<AnalysisNode> Children = [];

    protected AnalysisStatementWithDomain(AnalysisBoundKinds kind,
        Declaration syntaxNode,
        ISymbol domainSymbol,
        AnalysisNode? parent) :
        base(kind, syntaxNode, parent)
    {
        _domainSymbolTable = domainSymbol.IsFunction 
            ? ((FunctionSymbol)domainSymbol).NamedMembers 
            : new DomainSymbolTable(domainSymbol);
        Children.Add(NameIdentifier);
    }


    public abstract AnalysisBlock? Body { get; }


    public override int ChildrenCount => Children.Count;


    public DomainSymbolTable GetDomainSymbolTable()
    {
        return _domainSymbolTable;
    }


    public override IEnumerable<AnalysisNode> GetChildren()
    {
        return Children;
    }


    internal override void AddChild(AnalysisNode child)
    {
        Children.Add(child);
        child.Parent = this;
    }


    /// <summary>
    ///     查找行标签符号
    /// </summary>
    /// <param name="label">行标签名</param>
    public LabelSymbol? LookupLabel(string label)
    {
        return _domainSymbolTable.LookupLabel(label);
    }


    /// <summary>
    ///     声明一个标签符号，如果已存在，返回<see langword="false" />
    /// </summary>
    /// <param name="labelSymbol">已有的标签符号</param>
    internal bool DeclareLabel(LabelSymbol labelSymbol)
    {
        return _domainSymbolTable.DeclareLabel(labelSymbol);
    }


    /// <summary>
    ///     查找本地符号
    /// </summary>
    /// <param name="identifier">本地符号名标识符</param>
    public LocalSymbol? LookupLocal(Identifier identifier)
    {
        return _domainSymbolTable.LookupLocalSymbol(identifier.Value,
            identifier.GetFlags(SyntaxNodeFlags.OptionGlobalVariables)) as LocalSymbol;
    }


    /// <summary>
    ///     声明一个本地符号
    /// </summary>
    /// <param name="localSymbol">待添加的本地符号</param>
    /// <returns>如果符号名已存在，返回<see langword="false" /></returns>
    internal bool DeclareLocal(LocalSymbol localSymbol)
    {
        return _domainSymbolTable.DeclareSymbol(localSymbol);
    }
}